package com.example.backetballgame.gui;


import com.example.backetballgame.item.GameItem;
import com.example.backetballgame.item.Store;
import com.example.backetballgame.item.StorePotion;
import com.example.backetballgame.player.Player;
import com.example.backetballgame.store.StoreManage;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import java.util.List;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.stream.Collectors;

/**
 * This class represents the frame of the player shop, which contains the athlete page, potion page and shopping cart.
 */
public class PlayerShopFrame extends JFrame {

    // The athlete page
    private JPanel athletePanel;
    private JPanel athleteListPanel;
    private JPanel athleteInfoPanel;
    // The potion page
    private JPanel potionPanel;
    private JPanel potionListPanel;
    private JPanel potionInfoPanel;
    // The shopping cart
    private JPanel cartPanel;
    private JLabel cartTotalPriceLabel;

    private int totalPrice = 0;

    private BattlePreparationFrame buyPlayerFrame;

    private Store store;

    /**
     * Constructor for the PlayerShopFrame class.
     */
    public PlayerShopFrame() {
        setTitle("Game Store");
        setSize(800, 600);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        initUI();


        this.store = StoreManage.getStore();
        for (GameItem gameItem : store.getInventory()) {
            if (gameItem instanceof Player) {
                addAthleteCard((Player) gameItem);
            } else if (gameItem instanceof StorePotion) {
                addPotionCard((StorePotion) gameItem);
            }
        }

        setVisible(true);
    }

    /**
     * Constructor for the PlayerShopFrame class with a BuyPlayerFrame parameter.
     * @param buyPlayerFrame the BuyPlayerFrame object to be passed in
     */
    public PlayerShopFrame(BattlePreparationFrame buyPlayerFrame) {
        this.buyPlayerFrame = buyPlayerFrame;

        setTitle("Game Store");
        setSize(800, 600);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        initUI();

        this.store = StoreManage.getStore();
        for (GameItem gameItem : store.getInventory()) {
            if (gameItem instanceof Player) {
                addAthleteCard((Player) gameItem);
            } else if (gameItem instanceof StorePotion) {
                addPotionCard((StorePotion) gameItem);
            }
        }

        setVisible(true);
    }

    private void initUI() {
        // The athlete page
        athletePanel = new JPanel();
        athletePanel.setLayout(new BorderLayout());
        athleteListPanel = new JPanel();
        athleteListPanel.setLayout(new BoxLayout(athleteListPanel, BoxLayout.Y_AXIS));
        JScrollPane athleteScrollPane = new JScrollPane(athleteListPanel);
        athleteInfoPanel = new JPanel();
        athleteInfoPanel.setLayout(new GridLayout(3, 1));

        athletePanel.add(athleteScrollPane, BorderLayout.CENTER);
        athletePanel.add(athleteInfoPanel, BorderLayout.EAST);

        // The potion page
        potionPanel = new JPanel();
        potionPanel.setLayout(new BorderLayout());
        potionListPanel = new JPanel();
        potionListPanel.setLayout(new BoxLayout(potionListPanel, BoxLayout.Y_AXIS));
        JScrollPane potionScrollPane = new JScrollPane(potionListPanel);
        potionInfoPanel = new JPanel();
        potionInfoPanel.setLayout(new GridLayout(3, 2));


        potionPanel.add(potionScrollPane, BorderLayout.CENTER);
        potionPanel.add(potionInfoPanel, BorderLayout.EAST);

        // The shopping cart
        cartPanel = new JPanel();
        cartPanel.setLayout(new GridLayout(1, 5));

        cartTotalPriceLabel = new JLabel();
        cartTotalPriceLabel.setText("Total Price: 0");
        cartPanel.add(cartTotalPriceLabel);

        // Add the Back and Purchase buttons
        JButton backButton = new JButton("Back");
        JButton purchaseButton = new JButton("Purchase");
        cartPanel.add(backButton);
        cartPanel.add(purchaseButton);

        purchaseButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // Check if there is enough money
                if (StoreManage.getTotalMonty() < totalPrice) {
                    JOptionPane.showMessageDialog(null, "Not enough money");
                    return;
                }

                for (GameItem gameItem : store.getInventory()) {
                    if (gameItem.getQuantity() == 0) {
                        continue;
                    }
                    if (gameItem instanceof Player) {
                        StoreManage.getPlayers().add((Player) gameItem);
                    }
                    if (gameItem instanceof StorePotion) {
                        StoreManage.saveStorePotion((StorePotion) gameItem);
                    }
                }

                StoreManage.saveTotalMonty(StoreManage.getTotalMonty() - totalPrice);
                JOptionPane.showMessageDialog(null, "Successfully purchased, current balance " + StoreManage.getTotalMonty());

                athleteListPanel.removeAll();
                List<Player> allPlayers = store.getInventory().stream().filter(it -> it instanceof Player)
                        .map(it -> ((Player) it)).collect(Collectors.toList());
                for (Player item : allPlayers) {
                    if (item.getQuantity() !=0) {
                        store.removeItem(item);
                    }else {
                        addAthleteCard(item);
                    }
                }
                athleteListPanel.revalidate();

                calculateTotalPrice();
            }
        });

        backButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                dispose();
                if (buyPlayerFrame != null) {
                    buyPlayerFrame.refresh();
                }
            }
        });

        // The product page
        JPanel productPanel = new JPanel();
        productPanel.setLayout(new GridLayout(1, 2));
        productPanel.add(athletePanel);
        productPanel.add(potionPanel);

        // The layout of the entire frame
        setLayout(new BorderLayout());
        add(productPanel, BorderLayout.CENTER);
        add(cartPanel, BorderLayout.SOUTH);
    }


    /**
     * The main function of the PlayerShopFrame class.
     * @param args an array of command-line arguments for the application
     */
    public static void main(String[] args) {
        new PlayerShopFrame();

    }

    /**
     * Adds an athlete card to the athlete list panel.
     * @param player the Player object to be added
     */
    private void addAthleteCard(Player player) {
        JPanel cardPanel = new JPanel();
        cardPanel.setLayout(new GridLayout(1, 3));
        ImageIcon icon = new ImageIcon(getClass().getClassLoader().getResource("athlete.jpg"));
        Image image = icon.getImage().getScaledInstance(80, 80, Image.SCALE_SMOOTH);
        JLabel imageLabel = new JLabel(new ImageIcon(image));
        imageLabel.setPreferredSize(new Dimension(45, 45));
        imageLabel.setBackground(Color.RED);
        cardPanel.add(imageLabel);
        JPanel infoPanel = new JPanel(new GridLayout(6, 1));
        JLabel nameLabel = new JLabel("Name: " + player.getName());
        JLabel strengthLabel = new JLabel("Strength: " + player.getStrength());
        JLabel defenseLabel = new JLabel("Defense: " + player.getDefense());

//        StringJoiner stringJoiner = new StringJoiner(",");
////        for (Skill skill : player.getSkillList()) {
////            stringJoiner.add(skill.getName());
////        }
//        JLabel skillLabel = new JLabel("Skill: " + stringJoiner);
        JLabel priceLabel = new JLabel("Price: " + player.getPrice());

        JRadioButton radioButton = new JRadioButton();
        radioButton.setActionCommand(player.getGuid().toString());
        radioButton.addActionListener(event -> {
            Integer playerNumber = Integer.valueOf(radioButton.getActionCommand());
            store.getInventory().stream().filter(it -> it instanceof Player)
                    .map(it -> ((Player) it))
                    .filter(it -> Objects.equals(it.getGuid(), playerNumber)).findFirst()
                    .ifPresent(it -> {
                        it.setQuantity(radioButton.isSelected() ? 1 : 0);
                    });

            calculateTotalPrice();
        });
        radioButton.setHorizontalAlignment(SwingConstants.CENTER);

        JPanel quantityPanel = new JPanel(new BorderLayout());
        quantityPanel.add(radioButton, BorderLayout.CENTER);

        infoPanel.add(nameLabel);
        infoPanel.add(strengthLabel);
        infoPanel.add(defenseLabel);
        infoPanel.add(priceLabel);

        cardPanel.add(infoPanel);
        cardPanel.add(quantityPanel);
        athleteListPanel.add(cardPanel);
    }

    /**
     * Adds a number change event to a GameItem object and a JFormattedTextField object.
     * @param player the GameItem object to be added
     * @param quantityField the JFormattedTextField object to be added
     */
    private void addNumChangeEvent(GameItem player, JFormattedTextField quantityField) {
        quantityField.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent e) {
                if (quantityField.getText() == null || quantityField.getText().equals("")) {
                    return;
                }
                int count = Integer.parseInt(quantityField.getText());
                player.setQuantity(count);
                calculateTotalPrice();
            }


            @Override
            public void removeUpdate(DocumentEvent e) {
                calculateTotalPrice();
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                calculateTotalPrice();
            }
        });
    }

    /**
     * Calculates the total price of all items in the shopping cart.
     */
    private void calculateTotalPrice() {
        totalPrice = 0;

        for (GameItem gameItem : store.getInventory()) {
            if (gameItem.getQuantity() == 0) {
                continue;
            }
            totalPrice += gameItem.getPrice() * gameItem.getQuantity(); } cartTotalPriceLabel.setText("Total Price: " + totalPrice); }

    /**
     * Adds a potion card to the potion list panel.
     * @param storePotion the StorePotion object to be added
     */
    private void addPotionCard(StorePotion storePotion) {
        JPanel cardPanel = new JPanel();
        cardPanel.setLayout(new GridLayout(1, 3));
        ImageIcon icon = new ImageIcon(getClass().getClassLoader().getResource("w260.jpeg"));
        Image image = icon.getImage().getScaledInstance(80, 80, Image.SCALE_SMOOTH);
        JLabel imageLabel = new JLabel(new ImageIcon(image));
        imageLabel.setPreferredSize(new Dimension(45, 45));
        imageLabel.setBackground(Color.RED);
        cardPanel.add(imageLabel);
        JPanel infoPanel = new JPanel(new GridLayout(4, 1));
        JLabel nameLabel = new JLabel("Name: " + storePotion.getName());
        JLabel effectLabel = new JLabel("Effect: " + storePotion.getEffect().getType());
        JLabel priceLabel = new JLabel("Price: " + storePotion.getPrice());

        JFormattedTextField quantityField = new JFormattedTextField(NumberFormat.getIntegerInstance());
        quantityField.setValue(storePotion.getQuantity());
        quantityField.setColumns(2);

        addNumChangeEvent(storePotion, quantityField);

        JPanel quantityPanel = new JPanel(new BorderLayout());
        quantityPanel.add(quantityField);

        infoPanel.add(nameLabel);
        infoPanel.add(effectLabel);
        infoPanel.add(priceLabel);

        cardPanel.add(infoPanel);
        cardPanel.add(quantityPanel);
        potionListPanel.add(cardPanel);
    }
}